<template>
	<view class="container">
		<view class="form">
			<view class="form-item">
				<text class="label">1. 选择目录</text>
				<button class="select-btn" @click="selectDirectory">选择文件夹</button>
				<text class="path-text">{{ selectedDirectory || '未选择' }}</text>
			</view>
			
			<view class="form-item">
				<text class="label">2. 设置目标文件后缀</text>
				<input class="input" v-model="fileExtension" placeholder="例如: .mp4, .txt" />
			</view>
			
			<view class="form-item">
				<text class="label">3. 选择输出Excel表</text>
				<picker @change="bindPickerChange" :value="excelIndex" :range="excelList" range-key="name">
					<view class="picker">
						{{ excelList.length > 0 ? excelList[excelIndex].name : '请先创建Excel表' }}
					</view>
				</picker>
			</view>

			<view class="form-item">
				<text class="label">4. 编写自定义处理脚本</text>
				
				<view class="script-selector">
					<text class="selector-label">选择预设脚本:</text>
					<picker @change="bindScriptChange" :value="scriptIndex" :range="scriptOptions" range-key="name">
						<view class="picker">
							{{ scriptOptions[scriptIndex].name }}
						</view>
					</picker>
				</view>
				
				<!-- 
					由于 uni-app H5 编译存在BUG, 会将 <textarea> 错误编译为 <input>,
					导致无法多行输入和自动增高。
					因此，在H5端我们使用 contenteditable 的 div 来作为替代方案。
				-->
				<!-- #ifdef H5 -->
				<div
					ref="scriptEditor"
					class="script-input" 
					contenteditable="true"
					@input="handleScriptInput"
					:data-placeholder="placeholder"
				></div>
				<!-- #endif -->
				
				<!-- #ifndef H5 -->
				<textarea ref="scriptTextarea" class="script-input" :value="customScript" @input="handleScriptInput" placeholder="请输入JavaScript脚本..." maxlength="10000"></textarea>
				<!-- #endif -->

				<view class="script-desc">
					<text>脚本将接收一个文件信息数组 `files` 作为输入，每个文件包含路径和元数据，需返回一个处理后的对象数组。</text>
					<text>示例: return files.map(file => ({ '文件名': file.path, '时长': file.metadata.duration }));</text>
				</view>
			</view>
		</view>
		
		<view class="footer">
			<button class="submit-btn" @click="startExtraction">开始提取</button>
		</view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			selectedDirectory: '',
			fileExtension: '.mp4',
			customScript: `// files 是一个包含所有匹配文件信息的数组
// 每个文件对象包含: { path: '相对路径', metadata: { duration, size, width, height, ... } }
return files.map(file => {
	// 示例：提取文件名和元数据
	const parts = file.path.split('/');
	const fileName = parts[parts.length - 1];
	const duration = file.metadata.duration || 0;
	const size = file.metadata.size || 0;
	
	return {
		'文件路径': file.path,
		'文件名': fileName,
		'时长(秒)': Math.round(duration),
		'文件大小(MB)': Math.round(size / 1024 / 1024 * 100) / 100
	};
});
`,
			excelList: [],
			excelIndex: 0,
			selectedFiles: [],
			placeholder: '请输入JavaScript脚本...',
			scriptIndex: 0,
			scriptOptions: [
				{
					name: '请选择脚本',
					content: ''
				}
			],
			// #ifdef APP-PLUS
			nativeFilePaths: [],
			androidUri: null,
			scanQueue: [],
			scannedFiles: [],
			totalProcessed: 0,
			scanStartTime: null,
			originalTreeUri: null
			// #endif
		}
	},
	onLoad() {
		this.loadExcelList();
		this.loadScriptOptions();
	},
	onShow() {
		// 重新加载脚本列表，以防用户在脚本管理页面做了修改
		this.loadScriptOptions();
	},
	mounted() {
		// #ifdef H5
		// 初始化 contenteditable div 的内容
		if (this.$refs.scriptEditor) {
			this.$refs.scriptEditor.innerText = this.customScript;
		}
		// #endif
	},
	methods: {
		loadExcelList() {
			this.excelList = uni.getStorageSync('excelList') || []
			if (this.excelList.length === 0) {
				uni.showToast({
					title: '请先去"Excel表管理"创建表格',
					icon: 'none',
					duration: 2000
				})
			}
		},
		bindPickerChange(e) {
			this.excelIndex = e.detail.value
		},
		loadScriptOptions() {
			const scriptList = uni.getStorageSync('scriptList') || [];
			this.scriptOptions = [
				{
					name: '请选择脚本',
					content: ''
				},
				...scriptList.map(script => ({
					name: script.name,
					content: script.content,
					description: script.description
				}))
			];
		},
		bindScriptChange(e) {
			this.scriptIndex = e.detail.value;
			if (this.scriptIndex > 0) {
				const selectedScript = this.scriptOptions[this.scriptIndex];
				this.customScript = selectedScript.content;
				
				// #ifdef H5
				if (this.$refs.scriptEditor) {
					this.$refs.scriptEditor.innerText = this.customScript;
				}
				// #endif
				
				uni.showToast({
					title: `已选择: ${selectedScript.name}`,
					icon: 'success',
					duration: 1500
				});
			}
		},
		selectDirectory() {
			// #ifdef H5
			const input = document.createElement('input');
			input.type = 'file';
			input.webkitdirectory = true;
			input.multiple = true;

			// 隐藏元素
			input.style.position = 'absolute';
			input.style.top = '-9999px';
			input.style.left = '-9999px';
			input.style.opacity = '0';
			
			// 将元素添加到页面并设置事件监听
			document.body.appendChild(input);
			input.addEventListener('change', (event) => {
				this.onFileChange(event);
				// 使用后移除元素，保持DOM清洁
				document.body.removeChild(input);
			});
			
			input.click();
			// #endif
			
			// #ifdef APP-PLUS
			if (uni.getSystemInfoSync().platform == 'android') {
				this.selectDirectoryAndroid();
			} else {
				uni.showToast({ title: '该功能目前仅支持Android App', icon: 'none' });
			}
			// #endif
		},
		handleScriptInput(event) {
			// #ifdef H5
			this.customScript = event.target.innerText;
			// #endif

			// #ifndef H5
			this.customScript = event.detail.value;
			// #endif
		},
		// #ifdef APP-PLUS
		selectDirectoryAndroid() {
			const Intent = plus.android.importClass("android.content.Intent");
			const main = plus.android.runtimeMainActivity();
			const REQUEST_CODE = 1001;
		
			const oldOnActivityResult = main.onActivityResult;
			main.onActivityResult = (requestCode, resultCode, data) => {
				const Activity = plus.android.importClass("android.app.Activity");
				if (requestCode === REQUEST_CODE && resultCode === Activity.RESULT_OK) {
					const uri = data.getData();
					if (uri) {
						try {
							// 最终修复：通过 Activity 获取唯一的 ApplicationContext，这是最标准的安卓做法
							const context = main.getApplicationContext();
							const contentResolver = context.getContentResolver();
							const flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
							// 最终修复：使用 invoke 调用原生方法，避免因JS桥接问题导致方法找不到
							plus.android.invoke(contentResolver, 'takePersistableUriPermission', uri, flags);
							
							this.androidUri = uri.toString();
							this.listFilesFromAndroidUri(uri);
						} catch(e) {
							console.error("Permission error: " + e);
							uni.showModal({
								title: '获取目录权限失败',
								content: `错误详情: ${e.message || '无详细信息'}`,
								showCancel: false
							});
						}
					}
				}
				main.onActivityResult = oldOnActivityResult;
			};
			
			const intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
			main.startActivityForResult(intent, REQUEST_CODE);
		},
		listFilesFromAndroidUri(uri) {
			uni.showLoading({ title: '开始扫描...' });
			
			try {
				const DocumentsContract = plus.android.importClass("android.provider.DocumentsContract");
				const context = plus.android.runtimeMainActivity().getApplicationContext();
				
				// 获取目录名称
				const uriString = uri.toString();
				const lastSlash = uriString.lastIndexOf('/');
				this.selectedDirectory = lastSlash > 0 ? decodeURIComponent(uriString.substring(lastSlash + 1)) : '所选目录';
				
				// 重置扫描数据
				this.nativeFilePaths = [];
				this.scanQueue = [{
					uri: uri, 
					path: '', 
					treeUri: uri,
					documentId: null // 根目录不需要documentId，会通过getTreeDocumentId获取
				}]; 
				this.scannedFiles = [];
				this.totalProcessed = 0;
				this.scanStartTime = Date.now();
				this.originalTreeUri = uri;
				
				// 开始扫描
				this.processNextBatch(DocumentsContract, context);
				
			} catch(e) {
				uni.hideLoading();
				uni.showModal({
					title: '扫描初始化失败',
					content: `错误: ${e.message || '无详细信息'}`,
					showCancel: false
				});
			}
		},
		
		// 简化的批处理方法
		processNextBatch(DocumentsContract, context) {
			const BATCH_SIZE = 30; // 减小批次大小，提高稳定性
			const MAX_FILES = 5000; // 降低最大文件数
			const MAX_DEPTH = 10; // 最大目录深度限制
			const SCAN_TIMEOUT = 30000; // 30秒扫描超时
			
			// 检查扫描超时
			const elapsedTime = Date.now() - this.scanStartTime;
			if (elapsedTime > SCAN_TIMEOUT) {
				uni.hideLoading();
				uni.showModal({
					title: '扫描超时',
					content: `扫描已进行${Math.round(elapsedTime/1000)}秒，为避免卡死已停止。\n\n已发现 ${this.scannedFiles.length} 个文件。\n\n建议选择更小的目录或减少子目录层级。`,
					showCancel: false,
					confirmText: '使用当前结果',
					success: () => {
						this.nativeFilePaths = [...this.scannedFiles];
					}
				});
				return;
			}
			
			if (this.scanQueue.length === 0) {
				// 扫描完成
				this.nativeFilePaths = [...this.scannedFiles]; // 复制数组
				uni.hideLoading();
				
				// 显示最终结果
				const finalInfo = [
					'🎉 扫描完成！',
					`总文件数: ${this.scannedFiles.length}`,
					`匹配文件数: ${this.getMatchedFilesCount()}`,
					`扫描用时: ${Math.round(elapsedTime/1000)}秒`,
					'',
					'发现的匹配文件:'
				];
				
				const matchedFiles = this.scannedFiles.filter(fileObj => {
					if (!this.fileExtension) return true;
					const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
					return fileObj && fileObj.path && fileObj.path.endsWith(targetExtension);
				});
				
				if (matchedFiles.length > 0) {
					finalInfo.push(...matchedFiles.slice(0, 10).map(fileObj => fileObj.path)); // 最多显示前10个文件
					if (matchedFiles.length > 10) {
						finalInfo.push(`... 还有 ${matchedFiles.length - 10} 个匹配文件`);
					}
				} else {
					finalInfo.push('无匹配文件发现');
				}
				
				uni.showModal({
					title: '扫描结果',
					content: finalInfo.join('\n'),
					showCancel: false,
					confirmText: '确定',
					success: () => {
						if (this.scannedFiles.length === 0) {
							uni.showModal({
								title: '可能原因分析',
								content: '未发现任何文件的可能原因：\n\n1. 选择的文件夹为空\n2. 文件夹中只有隐藏文件\n3. 没有访问权限\n4. URI解析错误\n\n请检查文件夹内容或重新选择。',
								showCancel: false
							});
						} else if (this.getMatchedFilesCount() === 0) {
							uni.showModal({
								title: '未找到匹配文件',
								content: `扫描到 ${this.scannedFiles.length} 个文件，但没有匹配 "${this.fileExtension}" 后缀的文件。\n\n请检查文件后缀设置是否正确。`,
								showCancel: false
							});
						}
					}
				});
				return;
			}
			
			// 处理当前批次
			const currentBatch = [];
			for (let i = 0; i < BATCH_SIZE && this.scanQueue.length > 0; i++) {
				const item = this.scanQueue.shift();
				
				// 检查目录深度，避免过深的递归
				const depth = (item.path.match(/\//g) || []).length;
				if (depth > MAX_DEPTH) {
					continue;
				}
				
				currentBatch.push(item);
			}
			
			if (currentBatch.length === 0) {
				// 当前批次为空，继续下一批
				setTimeout(() => {
					this.processNextBatch(DocumentsContract, context);
				}, 50);
				return;
			}
			
			this.processBatchDirectories(currentBatch, DocumentsContract, context);
		},
		
		// 处理批次中的目录
		processBatchDirectories(currentBatch, DocumentsContract, context) {
			let processedInBatch = 0;
			
			const processNextDirectory = () => {
				if (processedInBatch >= currentBatch.length) {
					// 当前批次处理完成
					this.totalProcessed += processedInBatch;
					
					// 更新进度
					const progress = this.scanQueue.length === 0 ? 100 : 
						Math.min(Math.round((this.totalProcessed / (this.totalProcessed + this.scanQueue.length)) * 100), 99);
					
					uni.showLoading({ 
						title: `扫描中... ${progress}%\n已发现 ${this.getMatchedFilesCount()} 个匹配文件` 
					});
					
					// 检查文件数量限制
					if (this.scannedFiles.length >= 5000) {
						uni.hideLoading();
						uni.showModal({
							title: '文件数量过多',
							content: `已扫描到 ${this.scannedFiles.length} 个文件，已停止扫描。\n\n建议选择更小的目录或使用更具体的文件后缀过滤。`,
							showCancel: false,
							success: () => {
								this.nativeFilePaths = [...this.scannedFiles];
							}
						});
						return;
					}
					
					// 继续处理下一批（异步调用，避免阻塞）
					setTimeout(() => {
						this.processNextBatch(DocumentsContract, context);
					}, 50);
					return;
				}
				
				// 处理当前目录
				const {uri: currentUri, path: currentPath, treeUri: currentTreeUri, documentId: currentDocumentId} = currentBatch[processedInBatch];
				
				// 使用原始tree URI（如果当前项没有treeUri则使用原始的）
				const useTreeUri = currentTreeUri || this.originalTreeUri;
				
				try {
					this.scanSingleDirectorySync(currentUri, currentPath, useTreeUri, currentDocumentId, DocumentsContract, context, (items) => {
						// 处理扫描结果
						for (const item of items) {
							if (item.isDirectory) {
								// 检查队列中是否已存在相同路径，避免重复
								const isDuplicate = this.scanQueue.some(queueItem => queueItem.path === item.path);
								if (!isDuplicate) {
									// 添加子目录到扫描队列
									this.scanQueue.push({
										uri: item.uri, 
										path: item.path, 
										treeUri: useTreeUri,
										documentId: item.originalDocumentId
									});
								}
							} else {
								// 添加文件到结果列表 - 优化：直接提取元数据
								this.processScannedFile(item, useTreeUri).then(fileObj => {
									if (fileObj) {
										this.scannedFiles.push(fileObj);
									}
									// 不匹配的文件不添加，也不抛出错误
								}).catch(() => {
									// 处理失败的文件添加基本信息（但仍要检查是否匹配后缀）
									const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
									if (item.path && item.path.endsWith(targetExtension)) {
										this.scannedFiles.push({
											path: item.path,
											metadata: {
												size: 0,
												duration: 0,
												width: 0,
												height: 0,
												mimeType: item.mimeType || '',
												error: '元数据提取失败'
											}
										});
									}
								});
							}
						}
						
						processedInBatch++;
						setTimeout(processNextDirectory, 10);
					});
					
				} catch (dirError) {
					processedInBatch++;
					setTimeout(processNextDirectory, 10);
				}
			};
			
			// 开始处理批次
			processNextDirectory();
		},
		
		// 同步扫描单个目录（简化版本）
		scanSingleDirectorySync(currentUri, currentPath, treeUri, documentId, DocumentsContract, context, callback) {
			try {
				const items = [];
				
				// 修复URI构建逻辑 - 关键修复
				let childrenUri;
				let targetDocumentId;
				
				if (currentPath === '') {
					// 根目录：使用tree document ID
					targetDocumentId = DocumentsContract.getTreeDocumentId(treeUri);
				} else {
					// 子目录：优先使用传入的documentId，如果没有则通过API获取
					if (documentId) {
						targetDocumentId = documentId;
					} else {
						targetDocumentId = DocumentsContract.getDocumentId(currentUri);
					}
				}
				
				// 始终使用原始的tree URI来构建查询URI
				childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(treeUri, targetDocumentId);
				
				// 查询目录内容
				const contentResolver = context.getContentResolver();
				const Document = plus.android.importClass("android.provider.DocumentsContract$Document");
				
				const projection = plus.android.newObject("java.lang.String[]", 3);
				projection[0] = Document.COLUMN_DOCUMENT_ID;
				projection[1] = Document.COLUMN_DISPLAY_NAME; 
				projection[2] = Document.COLUMN_MIME_TYPE;
				
				const cursor = plus.android.invoke(contentResolver, 'query', 
					childrenUri, projection, null, null, null
				);
				
				if (!cursor) {
					callback([]);
					return;
				}
				
				const moveToFirstResult = plus.android.invoke(cursor, 'moveToFirst');
				
				if (!moveToFirstResult) {
					plus.android.invoke(cursor, 'close');
					callback([]);
					return;
				}
				
				let itemCount = 0;
				
				do {
					try {
						itemCount++;
						
						// 根据实际的cursor结构读取数据
						const field0 = plus.android.invoke(cursor, 'getString', 0);
						const field1 = plus.android.invoke(cursor, 'getString', 1);
						const field2 = plus.android.invoke(cursor, 'getString', 2);
						
						// 正确解析字段映射
						let documentId, displayName, mimeType;
						
						// 简化的字段映射检查
						let mimeField = -1;
						let nameField = -1;
						let idField = -1;
						
						[field0, field1, field2].forEach((field, index) => {
							if (field) {
								if (field === 'vnd.android.document/directory' || 
								    field.startsWith('video/') || 
								    field.startsWith('audio/') || 
								    field.startsWith('image/') ||
								    field.startsWith('text/') ||
								    field.startsWith('application/')) {
									mimeField = index;
								} else if (field.includes('.') && !field.includes('/') && field.length < 100) {
									nameField = index;
								} else if (field.includes('/') || field.length > 50) {
									idField = index;
								}
							}
						});
						
						// 根据分析结果分配字段
						if (mimeField >= 0) {
							mimeType = [field0, field1, field2][mimeField];
							
							if (nameField >= 0) {
								displayName = [field0, field1, field2][nameField];
							} else {
								for (let i = 0; i < 3; i++) {
									if (i !== mimeField && i !== idField) {
										displayName = [field0, field1, field2][i];
										break;
									}
								}
							}
							
							if (idField >= 0) {
								documentId = [field0, field1, field2][idField];
							} else {
								documentId = field0;
							}
						} else {
							// 回退到简单映射
							documentId = field0;
							displayName = field1;
							mimeType = field2;
						}
						
						if (!displayName) {
							continue;
						}
						
						const itemPath = currentPath ? `${currentPath}/${displayName}` : displayName;
						
						if (mimeType === "vnd.android.document/directory") {
							// 是目录
							try {
								// 保存完整的document ID用于后续扫描
								let realDocumentId = documentId;
								
								// 如果documentId包含路径分隔符，提取最后部分作为显示用的ID
								let displayDocumentId = realDocumentId;
								if (documentId.includes('/')) {
									const parts = documentId.split('/');
									displayDocumentId = parts[parts.length - 1];
								}
								
								// 使用原始tree URI和完整的document ID构建子目录document URI
								const childUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, realDocumentId);
								
								const newDirItem = {
									isDirectory: true,
									uri: childUri,
									path: itemPath,
									originalDocumentId: realDocumentId,
									mimeType: mimeType
								};
								
								// 检查是否已存在相同路径的目录，避免重复
								const isDuplicate = this.scanQueue.some(item => item.path === itemPath);
								if (!isDuplicate) {
									items.push(newDirItem);
								}
								
							} catch (uriError) {
								// 构建失败时跳过这个目录，避免卡住
							}
							
						} else if (displayName && displayName.indexOf('.') > 0) {
							// 是文件
							items.push({
								isDirectory: false,
								path: itemPath,
								documentId: documentId,  // 保存document ID用于后续元数据提取
								mimeType: mimeType
							});
						}
						
					} catch (itemError) {
						// 忽略单个项目错误，继续处理
					}
				} while (plus.android.invoke(cursor, 'moveToNext'));
				
				plus.android.invoke(cursor, 'close');
				
				callback(items);
				
			} catch (error) {
				callback([]);
			}
		},
		// #endif
		onFileChange(event) {
			const files = event.target.files;
			if (files.length > 0) {
				this.selectedFiles = files;
				const firstPath = files[0].webkitRelativePath;
				this.selectedDirectory = firstPath.split('/')[0];
			}
		},
		startExtraction() {
			if (!this.fileExtension) {
				uni.showToast({ title: '请输入文件后缀', icon: 'none' });
				return;
			}
			if (this.excelList.length === 0) {
				uni.showToast({ title: '请选择输出的Excel表', icon: 'none' });
				return;
			}
			if (!this.customScript) {
				uni.showToast({ title: '请输入自定义脚本', icon: 'none' });
				return;
			}

			// #ifdef H5
			// H5环境：需要先提取元数据
			if (this.selectedFiles.length === 0) {
				uni.showToast({ title: '请选择目录', icon: 'none' });
				return;
			}
			
			const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
			const filePaths = Array.from(this.selectedFiles)
				.map(file => file.webkitRelativePath)
				.filter(path => path.endsWith(targetExtension));
			
			if (filePaths.length === 0) {
				uni.showToast({ title: '未找到匹配的文件', icon: 'none' });
				return;
			}

			// 显示开始提取元数据的信息
			uni.showLoading({
				title: `正在提取 ${filePaths.length} 个文件的元数据...`
			});

			// H5端：提取文件元数据
			this.extractFileMetadata(filePaths).then(files => {
				this.executeScriptWithFiles(files);
			}).catch(error => {
				uni.hideLoading();
				uni.showModal({
					title: '元数据提取失败',
					content: error.message || '获取文件信息时发生错误',
					showCancel: false
				});
			});
			// #endif
			
			// #ifdef APP-PLUS
			// Android环境：直接使用已经包含元数据的scannedFiles
			if (uni.getSystemInfoSync().platform == 'android') {
				if (!this.androidUri) {
					uni.showToast({ title: '请选择目录', icon: 'none' });
					return;
				}
				
				// 过滤出匹配后缀的文件（scannedFiles中已经是文件对象）
				const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
				const matchedFiles = this.scannedFiles.filter(fileObj => 
					fileObj && fileObj.path && fileObj.path.endsWith(targetExtension)
				);
				
				if (matchedFiles.length === 0) {
					// 用户友好的提示
					if (this.scannedFiles.length > 0) {
						const fileTypes = [...new Set(this.scannedFiles.map(fileObj => {
							if (!fileObj || !fileObj.path) return '未知';
							const lastDot = fileObj.path.lastIndexOf('.');
							return lastDot > 0 ? fileObj.path.substring(lastDot) : '无后缀';
						}))];
						
						uni.showModal({
							title: '未找到匹配的文件',
							content: `扫描到 ${this.scannedFiles.length} 个文件，但没有匹配 "${targetExtension}" 后缀的文件。\n\n发现的文件类型：\n${fileTypes.join(', ')}\n\n请检查后缀输入是否正确。`,
							showCancel: false
						});
					} else {
						uni.showToast({ title: '未找到匹配的文件', icon: 'none' });
					}
					return;
				}

				// Android端：直接使用已包含元数据的文件
				this.executeScriptWithFiles(matchedFiles);
			} else {
				uni.showToast({ title: '该功能目前仅支持Android App', icon: 'none' });
			}
			// #endif
		},
		
		// 执行自定义脚本的通用方法
		executeScriptWithFiles(files) {
			uni.hideLoading();
			
			// 显示处理完成的信息
			uni.showToast({
				title: `处理完成：${files.length} 个文件`,
				icon: 'success',
				duration: 1500
			});

			// 执行自定义脚本
			try {
				const scriptFunction = new Function('files', this.customScript);
				const result = scriptFunction(files);

				if (!Array.isArray(result)) {
					throw new Error("脚本必须返回一个数组");
				}

				// 跳转到数据确认页面
				const selectedExcel = this.excelList[this.excelIndex];
				
				uni.setStorageSync('tempExtractData', {
					excelId: selectedExcel.id,
					extractedData: result
				});

				uni.navigateTo({
					url: '/pages/file/form'
				});

			} catch (e) {
				uni.showModal({
					title: '脚本执行错误',
					content: e.message,
					showCancel: false
				});
			}
		},
		extractFileMetadata(filePaths) {
			return new Promise((resolve, reject) => {
				const files = [];
				let processedCount = 0;
				const totalCount = filePaths.length;

				if (totalCount === 0) {
					resolve([]);
					return;
				}

				// 处理每个文件
				filePaths.forEach((filePath, index) => {
					const fileInfo = {
						path: filePath,
						metadata: {
							size: 0,
							duration: 0,
							width: 0,
							height: 0,
							mimeType: '',
							error: null
						}
					};

					// #ifdef H5
					// H5环境：使用File API和video元素获取元数据
					this.getH5FileMetadata(filePath, fileInfo).then(() => {
						files[index] = fileInfo;
						processedCount++;
						
						// 更新进度
						if (processedCount % 5 === 0 || processedCount === totalCount) {
							uni.showLoading({
								title: `处理中... ${processedCount}/${totalCount}`
							});
						}
						
						if (processedCount === totalCount) {
							resolve(files);
						}
					}).catch(error => {
						fileInfo.metadata.error = error.message;
						files[index] = fileInfo;
						processedCount++;
						
						if (processedCount === totalCount) {
							resolve(files);
						}
					});
					// #endif

					// #ifdef APP-PLUS
					// APP环境：使用Android MediaMetadataRetriever
					this.getAndroidFileMetadata(filePath, fileInfo).then(() => {
						files[index] = fileInfo;
						processedCount++;
						
						// 更新进度
						if (processedCount % 5 === 0 || processedCount === totalCount) {
							uni.showLoading({
								title: `处理中... ${processedCount}/${totalCount}`
							});
						}
						
						if (processedCount === totalCount) {
							resolve(files);
						}
					}).catch(error => {
						fileInfo.metadata.error = error.message;
						files[index] = fileInfo;
						processedCount++;
						
						if (processedCount === totalCount) {
							resolve(files);
						}
					});
					// #endif
				});
			});
		},
		// #ifdef H5
		// H5环境获取文件元数据
		getH5FileMetadata(filePath, fileInfo) {
			return new Promise((resolve, reject) => {
				// 查找对应的File对象
				const targetFile = Array.from(this.selectedFiles).find(file => 
					file.webkitRelativePath === filePath
				);
				
				if (!targetFile) {
					reject(new Error('文件未找到'));
					return;
				}

				// 获取基本文件信息
				fileInfo.metadata.size = targetFile.size;
				fileInfo.metadata.mimeType = targetFile.type;

				// 如果是视频文件，获取视频元数据
				if (targetFile.type.startsWith('video/')) {
					const video = document.createElement('video');
					video.preload = 'metadata';
					
					video.onloadedmetadata = () => {
						fileInfo.metadata.duration = video.duration || 0;
						fileInfo.metadata.width = video.videoWidth || 0;
						fileInfo.metadata.height = video.videoHeight || 0;
						
						// 释放资源
						URL.revokeObjectURL(video.src);
						resolve();
					};
					
					video.onerror = () => {
						URL.revokeObjectURL(video.src);
						// 即使视频元数据获取失败，也返回基本信息
						resolve();
					};
					
					// 设置超时，避免长时间等待
					setTimeout(() => {
						if (video.readyState < 1) {
							URL.revokeObjectURL(video.src);
							resolve(); // 超时也返回基本信息
						}
					}, 5000);
					
					video.src = URL.createObjectURL(targetFile);
				} else {
					// 非视频文件，直接返回
					resolve();
				}
			});
		},
		// #endif

		// #ifdef APP-PLUS
		// Android环境获取文件元数据
		getAndroidFileMetadata(filePath, fileInfo) {
			return new Promise((resolve, reject) => {
				try {
					if (uni.getSystemInfoSync().platform !== 'android') {
						resolve();
						return;
					}

					// 获取文件扩展名来判断文件类型
					const fileName = filePath.split('/').pop().toLowerCase();
					const isVideo = fileName.endsWith('.mp4') || fileName.endsWith('.avi') || 
					               fileName.endsWith('.mov') || fileName.endsWith('.mkv') || 
					               fileName.endsWith('.wmv') || fileName.endsWith('.flv');

					// 对于非视频文件，只返回基本信息
					if (!isVideo) {
						resolve();
						return;
					}

					// 简化的元数据模拟（实际项目中需要通过URI访问文件）
					// 由于Android文件访问的复杂性，这里提供模拟数据
					// 真实环境下需要根据具体的URI结构来获取文件元数据
					
					setTimeout(() => {
						// 模拟获取元数据的过程
						fileInfo.metadata.size = Math.floor(Math.random() * 100000000) + 1000000; // 1MB-100MB
						fileInfo.metadata.duration = Math.floor(Math.random() * 3600) + 10; // 10秒-1小时
						fileInfo.metadata.width = [720, 1080, 1920][Math.floor(Math.random() * 3)];
						fileInfo.metadata.height = [480, 720, 1080][Math.floor(Math.random() * 3)];
						fileInfo.metadata.mimeType = 'video/mp4';
						
						resolve();
					}, 100); // 模拟处理时间
					
				} catch (error) {
					resolve(); // 发生错误也继续处理
				}
			});
		},
		// #endif
		// #ifdef APP-PLUS
		// Android环境：处理扫描到的单个文件
		processScannedFile(item, treeUri) {
			return new Promise((resolve, reject) => {
				// 检查文件扩展名是否匹配目标后缀
				const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
				if (!item.path.endsWith(targetExtension)) {
					resolve(null); // 不匹配的文件返回null
					return;
				}

				const fileInfo = {
					path: item.path,
					metadata: {
						size: 0,
						duration: 0,
						width: 0,
						height: 0,
						mimeType: '',
						error: null
					}
				};

				// 获取文件扩展名来判断文件类型
				const fileName = item.path.split('/').pop().toLowerCase();
				const isVideo = fileName.endsWith('.mp4') || fileName.endsWith('.avi') || 
				               fileName.endsWith('.mov') || fileName.endsWith('.mkv') || 
				               fileName.endsWith('.wmv') || fileName.endsWith('.flv');

				if (isVideo) {
					// 尝试获取真实的视频元数据
					this.getRealVideoMetadata(item, treeUri, fileInfo).then(() => {
						resolve(fileInfo);
					}).catch(() => {
						// 如果获取失败，使用基本信息
						fileInfo.metadata.error = '无法获取视频元数据';
						fileInfo.metadata.mimeType = item.mimeType || '';
						resolve(fileInfo);
					});
				} else {
					// 非视频文件，返回基本信息
					fileInfo.metadata.mimeType = item.mimeType || '';
					resolve(fileInfo);
				}
			});
		},

		// 获取真实的视频元数据
		getRealVideoMetadata(item, treeUri, fileInfo) {
			return new Promise((resolve, reject) => {
				try {
					// 构建文件URI
					const context = plus.android.runtimeMainActivity().getApplicationContext();
					const DocumentsContract = plus.android.importClass("android.provider.DocumentsContract");
					
					// 这里需要根据文件路径找到对应的document ID
					// 由于Android文件系统的复杂性，我们先提供一个通用的处理方法
					this.getFileUriByPath(item, treeUri).then(fileUri => {
						if (!fileUri) {
							reject(new Error('无法构建文件URI'));
							return;
						}

						// 使用MediaMetadataRetriever获取真实元数据
						const MediaMetadataRetriever = plus.android.importClass("android.media.MediaMetadataRetriever");
						const retriever = new MediaMetadataRetriever();

						try {
							// 设置数据源
							plus.android.invoke(retriever, 'setDataSource', context, fileUri);

							// 获取时长（毫秒转秒）
							const durationStr = plus.android.invoke(retriever, 'extractMetadata', 
								MediaMetadataRetriever.METADATA_KEY_DURATION);
							if (durationStr) {
								fileInfo.metadata.duration = Math.round(parseInt(durationStr) / 1000);
							}

							// 获取视频尺寸
							const widthStr = plus.android.invoke(retriever, 'extractMetadata', 
								MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
							const heightStr = plus.android.invoke(retriever, 'extractMetadata', 
								MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);

							if (widthStr) fileInfo.metadata.width = parseInt(widthStr);
							if (heightStr) fileInfo.metadata.height = parseInt(heightStr);

							// 获取MIME类型
							const mimeType = plus.android.invoke(retriever, 'extractMetadata', 
								MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
							if (mimeType) fileInfo.metadata.mimeType = mimeType;

							// 获取文件大小（通过ContentResolver）
							this.getFileSizeByUri(fileUri, context).then(size => {
								if (size > 0) fileInfo.metadata.size = size;
								plus.android.invoke(retriever, 'release');
								resolve();
							}).catch(() => {
								plus.android.invoke(retriever, 'release');
								resolve(); // 即使获取大小失败也继续
							});

						} catch (e) {
							try {
								plus.android.invoke(retriever, 'release');
							} catch (releaseError) {
								// 忽略释放错误
							}
							reject(e);
						}

					}).catch(reject);

				} catch (error) {
					reject(error);
				}
			});
		},

		// 根据文件信息获取URI
		getFileUriByPath(item, treeUri) {
			return new Promise((resolve) => {
				try {
					if (!item.documentId) {
						resolve(null);
						return;
					}

					const DocumentsContract = plus.android.importClass("android.provider.DocumentsContract");
					
					// 使用document ID构建文件URI
					const fileUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, item.documentId);
					resolve(fileUri);
					
				} catch (error) {
					console.error('构建文件URI失败:', error);
					resolve(null);
				}
			});
		},

		// 根据URI获取文件大小
		getFileSizeByUri(fileUri, context) {
			return new Promise((resolve, reject) => {
				try {
					const contentResolver = context.getContentResolver();
					const DocumentsContract = plus.android.importClass("android.provider.DocumentsContract");
					const Document = plus.android.importClass("android.provider.DocumentsContract$Document");

					const projection = plus.android.newObject("java.lang.String[]", 1);
					projection[0] = Document.COLUMN_SIZE;

					const cursor = plus.android.invoke(contentResolver, 'query', 
						fileUri, projection, null, null, null
					);

					if (cursor && plus.android.invoke(cursor, 'moveToFirst')) {
						const sizeIndex = plus.android.invoke(cursor, 'getColumnIndex', Document.COLUMN_SIZE);
						if (sizeIndex >= 0) {
							const size = plus.android.invoke(cursor, 'getLong', sizeIndex);
							plus.android.invoke(cursor, 'close');
							resolve(size);
							return;
						}
					}

					if (cursor) {
						plus.android.invoke(cursor, 'close');
					}
					reject(new Error('无法获取文件大小'));

				} catch (error) {
					reject(error);
				}
			});
		},
		// #endif
		// 获取匹配文件数量的辅助方法
		getMatchedFilesCount() {
			if (!this.fileExtension) return this.scannedFiles.length;
			
			const targetExtension = this.fileExtension.startsWith('.') ? this.fileExtension : '.' + this.fileExtension;
			return this.scannedFiles.filter(fileObj => 
				fileObj && fileObj.path && fileObj.path.endsWith(targetExtension)
			).length;
		}
	}
}
</script>

<style>
.container {
	padding: 20px;
	min-height: 100vh;
	background-color: #f8f8f8;
	display: flex;
	flex-direction: column;
}
.form {
	flex: 1;
}
.form-item {
	background: #fff;
	border-radius: 12px;
	padding: 15px;
	margin-bottom: 20px;
}
.label {
	font-size: 14px;
	color: #333;
	margin-bottom: 10px;
	display: block;
	font-weight: 500;
}
.select-btn {
	background-color: #007AFF;
	color: #fff;
	font-size: 14px;
	margin-bottom: 10px;
	height: 40px;
	line-height: 40px;
}
.path-text {
	font-size: 12px;
	color: #666;
	word-break: break-all;
}
.input {
	width: 100%;
	height: 40px;
	border: 1px solid #ddd;
	border-radius: 8px;
	padding: 0 12px;
	font-size: 14px;
}
.picker {
	width: 100%;
	height: 40px;
	line-height: 40px;
	border: 1px solid #ddd;
	border-radius: 8px;
	padding: 0 12px;
	font-size: 14px;
}
.script-input {
	width: 100%;
	min-height: 150px;
	border: 1px solid #ddd;
	border-radius: 8px;
	padding: 12px;
	font-size: 14px;
	font-family: monospace;
	box-sizing: border-box;
	/* #ifdef H5 */
	white-space: pre-wrap; /* 允许div内容换行 */
	word-wrap: break-word; /* 允许长单词换行 */
	min-height: 150px;
	/* #endif */
}

/* #ifdef H5 */
.script-input:empty:before {
  content: attr(data-placeholder);
  color: #999;
}
/* #endif */

.script-desc {
	font-size: 12px;
	color: #999;
	margin-top: 10px;
	display: flex;
	flex-direction: column;
}
.footer {
	padding: 20px 0;
}
.submit-btn {
	background-color: #007AFF;
	color: #fff;
	border-radius: 8px;
	font-size: 16px;
}

.hidden-file-input {
	position: absolute;
	top: -9999px;
	left: -9999px;
	width: 1px;
	height: 1px;
	opacity: 0;
}

.script-selector {
	margin-bottom: 15px;
}

.selector-label {
	font-size: 12px;
	color: #666;
	margin-bottom: 8px;
	display: block;
}

.script-selector .picker {
	background-color: #f8f9fa;
	border-color: #007AFF;
	color: #007AFF;
}
</style> 